package JDK常用类库.集合;

import java.util.*;

/**关于Set的一道面试题
 * 这道题理解了,Set存的方式就理解透了,特重要！！同时深入理解下hashcode()这个方法！！！
 * @author zx
 * @create 2022-02-11 10:51
 */
public class Interview {
    public static void main(String[] args) {
        HashSet set = new HashSet();
        Person p1 = new Person(1001,"AA");
        Person p2 = new Person(1002,"BB");
        set.add(p1);
        set.add(p2);
        System.out.println(set);

        p1.name = "CC";
        set.remove(p1);
        System.out.println(set);
        /**
         * 为什么输出是两个？
         * 在HashSet底层，首先是个数组，将P1、P2存进来,具体的存储规则看正规的，P1、P2的哈希值大概率是不一样的；
         * 现在假设p1、p2的哈希值不一样(索引位置不一样)，则演示图如下：
         * 图中的位置是根据(1001,"AA")、(1002,"BB")算出的哈希值,进而算出的索引位置(以下解释切记此点)。
         * set.remove(p1):通过p1索引,一定可以找到(1001,"CC")的数据,现在想删除(1001,"CC"),首先的判断有没有；
         * 有的话,才可以删;对于set来讲,得先判断以下Hash值.
         * p1找,找到了(1001,"CC")这个对象了,然后算一下(1001,"CC")这个对象的hash值,通过这个hash值,一定可以找到
         * 数组中某个索引的位置,而这个位置,有极大概率,不是P1、P2的位置,然后在这个空的位置上remove(),相当于没有
         * 执行此操作;所以打印,就相当于两个都在。
         *
         */
        set.add(new Person(1001,"CC"));
        System.out.println(set);
        /**
         * 为什么输出是三个？
         * 因为添加的时候,是以(1001,"CC")的哈希值去找索引的,找到的索引大概率不是p1、p2的索引,所以是三个。
         */
        set.add(new Person(1001,"AA"));
        System.out.println(set);
        /**
         * 为什么输出四个？
         * 因为根据hash值判断完索引虽然相同,但是equals()仍然不同,添加成功。
         */

    }
}
class Person{
    int id;
    String name;

    public Person() {
    }

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
    //不重写这两个方法,运行结果是错的
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (id != person.id) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }
}
